<!DOCTYPE html>
<html lang=en style="font-size: 37.5px">

<head>
    <meta charset=utf-8>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <title>人脸检测</title>
    <script src="https://cdn.jsdelivr.net/gh/eduardolundgren/tracking.js/build/tracking-min.js"></script>
    <script src="https://cdn.jsdelivr.net/gh/eduardolundgren/tracking.js/build/data/face-min.js"></script>
</head>
<style>
    [v-cloak] {
        display: none;
    }

    body {
        background: #000;
        margin: 0;
        padding: 0;
    }
    .iframe-body{
        width: 100%;
    }

    .face-capture {
        display: relative;
        flex-direction: column;
        align-items: center;
        justify-content: center;
    }

    .mask-bg {
        position: relative;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
    }

    .mask-bg .mask-user {
        width: 388px;
        height: 388px;
        overflow: hidden;
        border-radius: 50%;
        border: 5px solid #052c74;
    }

    .mask-user-line {
        border: 3px dotted #59abed;
        padding: 10px;
        border-radius: 50%;
        width: 400px;
        height: 400px;
    }

    @media screen and (max-width: 1370px) {
        .mask-bg .mask-user {
            width: 300px;
            height: 300px;
            border: 3px solid #052c74;
            border-radius: 50%;
            /* overflow: hidden; */
        }

        .mask-user-line {
            border: 3px dotted #59abed;
            padding: 10px;
            border-radius: 50%;
            width: 305px;
            height: 305px;
        }
    }


    .face-capture video,
    .face-capture canvas {
        position: relative;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        width: 135%;
        /* height: 110%; */
        /* object-fit: cover; */
        z-index: 2;
        /* background-repeat: no-repeat; */
        /* background-size: 100% 100%; */
    }

    .face-capture canvas {
        z-index: 2;
    }

    .face-capture .img-cover {
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        width: 100%;
        height: 100%;
        object-fit: cover;
        z-index: 2;
        background-repeat: no-repeat;
        background-size: 100% 100%;
    }

    .face-capture .rect {
        border: .1px solid #d9e0d941;
        position: relative;
        z-index: 3;
    }

    .face-capture .control-container {
        margin-top: 10rem;
        position: relative;
        width: 100%;
        height: 100%;
        object-fit: cover;
        z-index: 4;
        background-repeat: no-repeat;
        background-size: 100% 100%;
    }

    .title {
        text-align: center;
        color: #656565;
        padding-top: 3rem;
        font-size: 24px;
    }

    @media screen and (max-width: 1370px) {
        .title {
            text-align: center;
            color: #656565;
            padding-top: 1rem;
            font-size: 20px;
        }
    }

    .face-capture .close {
        width: 0.8rem;
        height: 0.8rem;
    }

    .tip {
        padding: 9px;
        font-size: 18px;
        color: #103044;
        background: #6CCFFF;
        border-radius: 36px;
        width: 240px;
        margin: 0 auto;
    }

    .tip-error {
        padding: 9px;
        font-size: 18px;
        color: #fff;
        background: #FF5555;
        border-radius: 36px;
        width: 240px;
        margin: 0 auto;
    }

    .container .skills {
        text-align: right;
        padding-right: 20px;
        line-height: 40px;
        color: #656565;
        border: 2px solid #656565;
    }

    .js {
        width: 65%;
        background-color: #2196F3;
    }

    .swiper-animate {
        position: relative;
        width: 100%;
        height: 8px;
        left: 0;
        top: 0;
        /* z-index: 2; */

        animation: scan 5s ease-in-out infinite;
        -webkit-animation: scan 5s ease-in-out infinite;
    }

    @keyframes scan {
        0% {
            top: 50px;
            background: linear-gradient(to bottom, transparent, #e2dfdfbd);
        }

        /*网格移动到显示区域的外面*/
        50% {
            top: 360px;
        }

        100% {
            top: 50px;
            background: linear-gradient(to top, transparent, #e2dfdfbd);
        }
    }

    @-webkit-keyframes scan {
        0% {
            top: 0;
        }

        /*网格移动到显示区域的外面*/
        50% {
            top: 360px;
        }

        100% {
            top: 10px;
        }
    }
</style>

<body>
    
    <div id="app" class="mask-bg" v-cloak>
        <h2 class="title">{{scanTip}}</h2>
    </div>
</body>
<script src="/javascripts/vue.min.js" type="text/javascript"></script>
<script src="/javascripts/vue-resource.min.js" type="text/javascript"></script>
<script src="/javascripts/script.js" type="text/javascript"></script>
<script>
    const app = new Vue({
        el: "#app",
        data() {
            return {
                screenSize: {
                    width: 320,
                    height: 240
                },
                URL: null,
                streamIns: null, // 视频流
                showContainer: true, // 显示
                tracker: null,
                tipFlag: false, // 提示用户已经检测到
                flag: false, // 判断是否已经拍照
                context: null, // canvas上下文
                profile: [], // 轮廓
                removePhotoID: null, // 停止转换图片
                scanTip: '', // 提示文字
                imgUrl: '', // base64格式图片
                imgBase64Data: '', // base64格式(去头)
                isUserSuccess: 4, //0:中间状态 1：用户已对应 2：用户未对应 3:识别中 4.登陆
                skillswidth: 0,
                music: null,
                showFace: true,
                trackerTask: null,
                loginUrl: ''
            }
        },
        mounted() {
            this.baiduUser('/getBaiDuUser');
            this.playMusic();
        },
        methods: {
            // 向百度请求用户牵手
            baiduUser(url) {
                var that = this;
                Vue.http.post(url).then(function (res) {
                    localStorage.setItem("baiduKey", JSON.stringify(res['data']));
                    // that.playVideo();
                }, function (e) {

                });
            },
            login(){
                this.scanTip = '扫描中.....'
                this.playVideo();
            },
            // 访问用户媒体设备
            getUserMedia(constrains, success, error) {
                if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
                    //最新标准API
                    navigator.mediaDevices.getUserMedia(constrains).then(success).catch(error);
                } else if (navigator.webkitGetUserMedia) {
                    //webkit内核浏览器
                    navigator.webkitGetUserMedia(constrains).then(success).catch(error);
                } else if (navigator.mozGetUserMedia) {
                    //Firefox浏览器
                    navagator.mozGetUserMedia(constrains).then(success).catch(error);
                } else if (navigator.getUserMedia) {
                    //旧版API
                    navigator.getUserMedia(constrains).then(success).catch(error);
                } else {
                    this.scanTip = "你的浏览器不支持访问用户媒体设备"
                }
            },
            success(stream) {
                this.streamIns = stream
                // webkit内核浏览器
                this.URL = window.URL || window.webkitURL
                if ("srcObject" in this.$refs.refVideo) {
                    this.$refs.refVideo.srcObject = stream
                } else {
                    this.$refs.refVideo.src = this.URL.createObjectURL(stream)
                }
                this.$refs.refVideo.onloadedmetadata = e => {
                    this.$refs.refVideo.play()
                    this.initTracker();
                    this.showContainer = true;
                }
            },
            musicSuccess(that) {
                // webkit内核浏览器
                this.URL = window.URL || window.webkitURL

                this.$refs.refAudio.src = '../img/ok.mp3';
                this.$refs.refAudio.onloadedmetadata = e => {
                    that.music = this.$refs.refAudio;
                }
            },
            play() {
                this.music.play();
            },
            error(e) {
                this.scanTip = "访问用户媒体失败" + e.name + "," + e.message;
            },
            playVideo() {
                this.isUserSuccess = 0;
                this.getUserMedia({
                    video: {
                        width: 320,
                        height: 240,
                        facingMode: "user"
                    } /* 前置优先 */
                }, this.success, this.error)
            },
            replayVideo() {
                this.isUserSuccess = 0;
                this.showFace = false;
                this.getUserMedia({
                    video: {
                        width: 320,
                        height: 240,
                        facingMode: "user"
                    } /* 前置优先 */
                }, this.success, this.error)
            },
            playMusic() {
                this.getUserMedia({
                    audio: {
                        facingMode: "user"
                    } /* 前置优先 */
                }, this.musicSuccess(this), this.error)
            },
            // 人脸捕捉
            initTracker() {
                this.context = this.$refs.refCanvas.getContext("2d") // 画布
                this.tracker = new tracking.ObjectTracker(['face']) // tracker实例
                this.tracker.setStepSize(0.7) // 设置步长
                this.tracker.on('track', this.handleTracked) // 绑定监听方法
                try {
                    this.trackerTask = tracking.track('#video', this.tracker) // 开始追踪
                } catch (e) {
                    this.scanTip = "访问用户媒体失败，请重试"
                }
            },
            // 追踪事件
            handleTracked(e) {
                if (e.data.length === 0) {
                    // this.scanTip = '未检测到人脸'
                } else {
                    if (!this.tipFlag) {
                        this.showFace = false;
                        // this.scanTip = '检测成功，请保持不动'
                    }
                    // 1秒后拍照，仅拍一次
                    if (!this.flag) {
                        this.flag = true
                        this.removePhotoID = setTimeout(() => {
                            this.tackPhoto()
                            this.trackerTask.stop();
                            // this.tipFlag = true
                        }, 1000)
                    }
                    // e.data.forEach(this.plot)
                }
            },
            // 绘制跟踪框
            plot({
                x,
                y,
                width: w,
                height: h
            }) {
                // 创建框对象
                this.profile = [];
                this.profile.push({
                    width: w,
                    height: h,
                    left: x,
                    top: y
                })
            },
            // 拍照
            tackPhoto() {
                this.context.drawImage(this.$refs.refVideo, 0, 0, this.screenSize.width, this.screenSize.height)
                // 保存为base64格式
                this.imgUrl = this.saveAsPNG(this.$refs.refCanvas)
                this.imgBase64Data = this.imgUrl.split(',')[1];
                /** 拿到base64格式图片之后就可以在this.compare方法中去调用后端接口比较了，也可以调用getBlobBydataURI方法转化成文件再去比较
                 * 我们项目里有一个设置个人头像的地方，先保存一下用户的图片，然后去拿这个图片的地址和当前拍照图片给后端接口去比较。
                 * */
                this.compare(this.imgUrl)
                this.close()
            },
            // Base64转文件
            getBlobBydataURI(dataURI, type) {
                var binary = window.atob(dataURI.split(',')[1]);
                var array = [];
                for (var i = 0; i < binary.length; i++) {
                    array.push(binary.charCodeAt(i));
                }
                return new Blob([new Uint8Array(array)], {
                    type: type
                });
            },
            compare(url) {
                let blob = this.getBlobBydataURI(url, 'image/png')

                let formData = new FormData()
                formData.append("file", blob, "file_" + Date.parse(new Date()) + ".png")
                // TODO 得到文件后进行人脸识别
            },
            // 保存为png,base64格式图片
            saveAsPNG(c) {
                return c.toDataURL('image/png', 0.3)
            },
            getNum() {
                var max = 1000;
                var min = 100;
                return Math.random() * (max - min) + min;
            },
            timer(num) {
                if (this.skillswidth < 100) {
                    setTimeout(() => {
                        this.skillswidth++;
                        if (this.skillswidth >= 98) {
                            this.skillswidth = 80;
                            this.timer(this.skillswidth, this.getNum())
                        } else {
                            this.timer(this.skillswidth, this.getNum())
                        };
                    }, num)
                }
            },

            // 关闭并清理资源
            close() {
                this.skillswidth=0;
                this.flag = false
                this.tipFlag = false
                this.showFailPop = false
                this.showContainer = false
                this.tracker && this.tracker.removeListener('track', this.handleTracked)
                this.tracker = null
                this.context = null
                this.profile = []
                this.scanTip = '扫描成功，识别中...';
                this.isUserSuccess = 3;
                this.timer(this.getNum());
                clearTimeout(this.removePhotoID);
                if (this.streamIns) {
                    this.streamIns.enabled = false
                    this.streamIns.getTracks().forEach(track => track.stop());
                    this.streamIns.getVideoTracks().forEach(track => track.stop());
                }
                this.streamIns = null;
                var baiduKey = JSON.parse(localStorage.getItem('baiduKey'))['data'];
                var that = this;

                setTimeout(() => {
                    Vue.http.post('/search', {
                        img: this.imgBase64Data
                    }, {
                        emulateJSON: true,
                        headers: {
                            'Content-Type': 'x-www-from-urlencoded'
                        }
                    }).then(function (res) {
                        this.skillswidth = 100;
                        switch (res['body']['error_code']) {
                            case 0:
                                var result = res['body']['result'];
                                that.play();
                                var userData = result['user_list'][0]['user_info'].split(',');
                                if (result['user_list'][0]['score'] > 80) {
                                    that.showContainer = false;
                                    that.loginUrl = userData[2] == '1' ? '../img/1.png' : '../img/0.png';

                                    that.scanTip = '欢迎你，' + userData[0] + userData[1];
                                    if (userData[2] == 1) {
                                        setTimeout(() => {
                                            window.location.href = "/zgjsc";
                                        }, 6000)
                                    } else {
                                        setTimeout(() => {
                                            window.location.href = "/zcfbt";
                                        }, 6000)
                                    }
                                    that.isUserSuccess = 1;
                                } else {
                                    that.skillswidth = 0;
                                    that.scanTip = '未授权用户'
                                    that.replayVideo();
                                    that.isUserSuccess = 2;

                                }
                                break;
                            default:
                                that.skillswidth = 0;
                                that.scanTip = '未授权用户'
                                that.replayVideo();
                                that.isUserSuccess = 2;

                                break;
                        }

                    }, function (e) {
                        this.skillswidth = 0;
                        that.isUserSuccess = 2;
                        that.replayVideo();
                    });
                }, 3000)
            }
        }

    })
</script>

</html>